// dm.h

// Copyright (C) 2010  traxex

// Author: 	traxex <traxex@yahoo.cn>
// Created: 	25 Jul 2010
// Version: 	1.0

#pragma once

namespace Traxex{
namespace Cuda{
template<class T>class GProxy;
	
//array proxy
template<class T,int N> class GProxy<T[N]>{
  public:
    explicit GProxy( T *dptr)    : dptr_(dptr){ }
    GProxy& operator=( const GProxy& old){
        if( dptr_ != (T*)old) d2dcpy( dptr_, (T*)old, N);
        return *this;
    }
	    
    operator T*()const {return dptr_;   }
	    
    GProxy<T> operator[]( int n){ 
        return GProxy<T>( dptr_[n]);  
    }

    GProxy& operator=( const T *hptr){
        h2dcpy( dptr_, hptr, N);
        return *this;
    }

    GProxy& operator<<( const T *hptr){
        h2dcpy( dptr_, hptr, N);
        return *this;
    }

    GProxy& operator>>( T *hptr){
        d2hcpy( hptr,  dptr_, N);
        return *this;
    }
	    
  protected:
    T	*dptr_;
};

//element proxy
template<class T> class GProxy{
  public:
    explicit GProxy( T *dptr) : dptr_(dptr){}
    explicit GProxy( T &dptr) : dptr_(&dptr){}

    operator T*()const {return dptr_;   }	    
    operator T()const{ 
        T tmp; 
        d2hcpy( &tmp, this->dptr_, 1);
        return tmp;
    }

    GProxy& operator=( const T tmp){
        h2dcpy( this->dptr_, &tmp, 1);
        return *this;
    }
  protected:
    T	*dptr_;
};


template<class T>class G
        : public GProxy<T>{
  public:
    typedef GProxy<T>	Proxy;

    G()
            : Proxy( *dmalloc<T>(1)){}

    G(const T& t)
            : Proxy( *dmalloc<T>(1)){
        Proxy::operator=(t);
    }

    G( const Proxy &src)
            : Proxy( *dmalloc<T>(1)){
        Proxy::operator=( src);
    }

    ~G(){
        dfree( this->dptr_);
    }

    template<typename PT>  G& operator=( const PT& tmp){
        Proxy::operator=(tmp);
        return *this;
    }
  private:
    G( const G&);
};

}
}
